#include "MsgMgr.h"

#include "Platform.h"
#include "packet.pb.h"

#include "Log.h"

CMsgMgr::CMsgMgr()
{
}


CMsgMgr::~CMsgMgr()
{
}

bool CMsgMgr::Init()
{
    bool bFlag = CNet::Init();
    if (!bFlag)
    {
        return false;
    }
    return true;
}


bool CMsgMgr::OnPacket(const int iSocket, char *pBuff, int iLen)
{
    bool bFlag = CNet::OnPacket(iSocket, pBuff, iLen);
    if (bFlag == false)
    {
        LOG_ERR("OnPacket Fail.Socket:%d Len:%d", iSocket, iLen);
        return false;
    }

    MsgMap::iterator itMsgMap = m_mapMsg.find(iSocket);
    if (itMsgMap == m_mapMsg.end())
    {
        SMsgData stMsgData;
        stMsgData.iSocket = iSocket;
        stMsgData.eState = ENM_ROLE_STATE_NEW;
        stMsgData.ullRoleID = 0;
        itMsgMap = m_mapMsg.insert(pair<int, SMsgData>(iSocket, stMsgData)).first;
        if (itMsgMap == m_mapMsg.end())
        {
            LOG_ERR("MapMsg Insert Fail.Socket:%d", iSocket);
            return false;
        }
    }

    comm::Packet pbPacket;
    if (pbPacket.ParseFromArray(pBuff, iLen) == false)
    {
        LOG_ERR("Parse Packet Fail.Socket:%d Len:%d", iSocket, iLen);
        return false;
    }
    else
    {
        comm::Head pbHead;
        pbHead.CopyFrom(pbPacket.head());
        pbHead.set_socket(iSocket);
        pbHead.set_roleid(itMsgMap->second.ullRoleID);
        
        CPlatform::Instance().Handle(pbHead, pbPacket.body());
    }
    return true;
}

bool CMsgMgr::OnAccept(const int iListenSocket, const int iClientSocket)
{
    bool bFlag = CNet::OnAccept(iListenSocket, iClientSocket);
    if (!bFlag)
    {
        return false;
    }

    MsgMap::iterator itMsgMap = m_mapMsg.find(iClientSocket);
    if (itMsgMap == m_mapMsg.end())
    {
        SMsgData stMsgData;
        stMsgData.iSocket = iClientSocket;
        stMsgData.ullRoleID = 0;
        stMsgData.eState = ENM_ROLE_STATE_NEW;
        m_mapMsg.insert(pair<int, SMsgData>(iClientSocket, stMsgData));
    }
    else
    {
        ull ullRoleID = itMsgMap->second.ullRoleID;
        if (ullRoleID != 0)
        {
            m_mapRole.erase(ullRoleID);
        }
    }
    return true;
}

bool CMsgMgr::OnClose(const int iSocket)
{
    MsgMap::iterator itMsgMap = m_mapMsg.find(iSocket);
    if (itMsgMap != m_mapMsg.end())
    {
        ull ullRoleID = itMsgMap->second.ullRoleID;
        if (ullRoleID != 0)
        {
            m_mapRole.erase(ullRoleID);
        }
    }
    m_mapMsg.erase(iSocket);

    return CNet::OnClose(iSocket);
}


comm::Head & CMsgMgr::CreateHeadFromReq(const comm::Head &pbReqHead, int iEnmCmd, int iRet, vector<string> *pRetMessage )
{
    static comm::Head pbResHead;
    pbResHead.Clear();

    comm::EnmModuleCmd enmModule = GetModuleFromCmd(pbReqHead.cmd());
    pbResHead.set_cmd(CreateCmd(enmModule, iEnmCmd));
    pbResHead.set_roleid(pbReqHead.roleid());
    pbResHead.set_seqid(pbReqHead.seqid());
    pbResHead.set_socket(pbReqHead.socket());
    pbResHead.set_retcode(iRet);
    if (pRetMessage != NULL && !pRetMessage->empty())
    {
        for (vector<string>::iterator vecIt = pRetMessage->begin(); vecIt != pRetMessage->end(); ++vecIt)
        {
            pbResHead.add_retmessage(*vecIt);
        }
    }
    return pbResHead;
}

comm::EnmModuleCmd CMsgMgr::GetModuleFromCmd(int iCmd)
{
    int iModule = iCmd / 10000;
    if (comm::EnmModuleCmd_IsValid(iModule))
    {
        return (comm::EnmModuleCmd)iModule;
    }
    else
    {
        return comm::ENM_MODULE_ERROR;
    }
}

void CMsgMgr::SendPacket(const ull ullRoleID, const google::protobuf::Message &pbMessage, const comm::EnmModuleCmd iModule, const int iCmd)
{
    RoleMap::iterator itMap = m_mapRole.find(ullRoleID);
    if (itMap == m_mapRole.end())
    {
        return;
    }

    SMsgData &stMsgData = itMap->second;

    if (stMsgData.iSocket <= 0 || stMsgData.eState != ENM_ROLE_STATE_OK)
    {
        return;
    }

    comm::Packet pbPacket;
    comm::Head pbHead;
    pbHead.set_cmd(iCmd);

    //报文头序列化
    char szBuff[MAX_DATA_SIZE];
    int iBuffSize = pbHead.ByteSize();
    if (!pbHead.SerializeToArray(szBuff, sizeof(szBuff)))
    {
        LOG_ERR("Head Serialize Fail.Size:%d", iBuffSize);
        return;
    }
   // pbPacket.set_head(szBuff, iBuffSize);

    //报文体序列化
    iBuffSize = pbMessage.ByteSize();
    if (!pbMessage.SerializeToArray(szBuff, sizeof(szBuff)))
    {
        LOG_ERR("Body Serialize Fail.Size:%d", iBuffSize);
        return;
    }
    pbPacket.set_body(szBuff, iBuffSize);


    //整个报文序列化
    iBuffSize = pbMessage.ByteSize();
    if (!pbPacket.SerializeToArray(szBuff, sizeof(szBuff)))
    {
        LOG_ERR("Packet Serialize Fail.Size:%d", iBuffSize);
        return;
    }

    int iSendSize = CNet::Send(stMsgData.iSocket, szBuff, iBuffSize);

    if (iSendSize <= 0)
    {
        LOG_ERR("Not Send.Socket:%d SendSize:%d BuffSize:%d", stMsgData.iSocket, iSendSize, iBuffSize);
    }
}

void CMsgMgr::SendPacket(const comm::Head &pbHead, const google::protobuf::Message &pbMessage)
{
    int iSocket = pbHead.socket();
    comm::EnmModuleCmd enmModule = GetModuleFromCmd(pbHead.cmd());
    int iCmd = GetEnmCmd(pbHead.cmd());

    MsgMap::iterator itMsgMap = m_mapMsg.find(iSocket);
    if (itMsgMap == m_mapMsg.end())
    {
        LOG_ERR("Can't Find Socket, Socket:%d Module:%d Cmd:%d", iSocket, enmModule, iCmd);
        return;
    }

    SMsgData &stMsgData = itMsgMap->second;
    if (iSocket <= 0 || stMsgData.eState == ENM_ROLE_STATE_ERROR)
    {
        LOG_ERR("Socket State Is Error, Socket:%d State:%d Module:%d Cmd:%d", iSocket, stMsgData.eState, enmModule, iCmd);
        return;
    }

    comm::Packet pbPacket;

    //报文头序列化
    char szBuff[MAX_DATA_SIZE];
    int iBuffSize = 0;
    pbPacket.mutable_head()->CopyFrom(pbHead);

    //报文体序列化
    iBuffSize = pbMessage.ByteSize();
    if (!pbMessage.SerializeToArray(szBuff, sizeof(szBuff)))
    {
        LOG_ERR("Body Serialize Fail.Size:%d", iBuffSize);
        return;
    }
    pbPacket.set_body(szBuff, iBuffSize);


    //整个报文序列化
    iBuffSize = pbMessage.ByteSize();
    if (!pbPacket.SerializeToArray(szBuff, sizeof(szBuff)))
    {
        LOG_ERR("Packet Serialize Fail.Size:%d", iBuffSize);
        return;
    }

    int iSendSize = CNet::Send(stMsgData.iSocket, szBuff, iBuffSize);

    if (iSendSize <= 0)
    {
        LOG_ERR("Not Send.Socket:%d SendSize:%d BuffSize:%d",stMsgData.iSocket, iSendSize, iBuffSize);
    }
}
